#include "message_parse.h"

#include <boost/asio.hpp>
using namespace boost;
using namespace boost::asio;

#include "utils/util.h"

MessageParse::MessageParse() : state_(State::eInit)
{

}

ParseResultState MessageParse::parse(std::size_t bytes_transferred)
{
    bufs_.commit(bytes_transferred);
    do
    {
        switch (state_)
        {
        case MessageParse::State::eInit:
        {
            if (bufs_.size() < sizeof(int16_t))
            {
                return ParseResultState::eNeedMore;
            }
            state_ = State::eParseTag;
            continue;
        }
        case MessageParse::State::eParseTag:
        {
            uint16_t startTag = 0;
            bufs_.sgetn((char*)&startTag, sizeof(startTag));
            startTag = ntohs(startTag);
            if (startTag == 0xDDEE)
            {
                state_ = State::eParseHeader;
                continue;
            }
            else
            {
                state_ = State::eInit;
                continue;
            }
        }
        case MessageParse::State::eParseHeader:
        {
            if (bufs_.size() < MSG_HEAD_LEN)
            {
                return ParseResultState::eNeedMore;
            }
            uint64_t msgid = 0;
            bufs_.sgetn((char*)&(msgid), sizeof(msgid));
            msgHeader_.msgID.msgID = ntoh64(msgid);

            uint16_t buflen = 0;
            bufs_.sgetn((char*)&(buflen), sizeof(buflen));
            msgHeader_.bufLen = ntohs(buflen);

            state_ = State::eParseData;
            break;
        }
        case MessageParse::State::eParseData:
            if (bufs_.size() < (std::size_t)msgHeader_.bufLen)
            {
                return ParseResultState::eNeedMore;
            }
            state_ = State::eInit;
            return ParseResultState::eSuc;

        default:
            return ParseResultState::eFailed;

        }
    } while (true);
    return ParseResultState::eSuc;
}

streambuf::mutable_buffers_type MessageParse::getMutableBufs()
{
    return bufs_.prepare(8 * 1024);
}
